<?php
declare (strict_types = 1);

namespace app\frontend\controller;

use app\frontend\model\TaskContent;
use app\frontend\model\TimeSlice;
use app\frontend\model\UserConfig;
use app\frontend\model\UserProject;
use think\facade\Db;
use think\facade\Filesystem;
use think\facade\Validate;

class Task extends Base
{
    // 任务列表页
    public function index()
    {
        // 找出当前用户所属的所有项目
        $userInfo = session('userInfo');
        $projectIds = UserProject::field('id,project_id')
            ->where('user_id', $userInfo['id'])
            ->column('project_id');
        $projects = \app\frontend\model\Project::field('id,name')->select($projectIds)->toArray();

        return view('', [
            'projects' => $projects
        ]);
    }

    // 任务列表数据接口
    public function list()
    {
        $page = request()->param('page');
        $limit = request()->param('limit');
        $project = request()->param('project');
        $status = request()->param('status');
        $name = request()->param('name');
        $plan = request()->param('plan');

        if ($status == 'all') {
            $status = [1, 2, 3, 4, 5];
        } else {
            $status = [$status];
        }

        $userInfo = session('userInfo');

        $query = \app\frontend\model\Task::with(['project'])
            ->field('id,project_id,name,start_time,end_time,status,priority')
            ->where('user_id', $userInfo['id']);
        if (!empty($plan)) {
            $query = $query->where('plan_id', $plan);
        }

        if ($project == 'all') {
            $taskList = $query->where([
                    ['name', 'like', '%'.$name.'%'],
                    ['status', 'in', $status],
                    ['pid', '=', 0]
                ])
                ->order('id', 'desc')
                ->paginate([
                    'list_rows' => $limit,
                    'var_page' => 'page',
                    'page' => $page,
                    'query' => [
                        'name' => $name,
                        'status' => $status
                    ]
                ]);
        } else {
            $taskList = $query->where([
                    ['name', 'like', '%'.$name.'%'],
                    ['project_id', '=', $project],
                    ['status', 'in', $status],
                    ['pid', '=', 0]
                ])
                ->order('id', 'desc')
                ->paginate([
                    'list_rows' => $limit,
                    'var_page' => 'page',
                    'page' => $page,
                    'query' => [
                        'name' => $name,
                        'project_id' => $project,
                        'status' => $status
                    ]
                ]);
        }

        $taskListData = $taskList->toArray()['data'];
        foreach ($taskListData as &$task) {
            $task['project'] = $task['project']['name'];
            if (empty($task['start_time'])) {
                $task['start_time'] = '未开始';
            } else {
                $task['start_time'] = date('Y-m-d H:i:s', $task['start_time']);
            }
            if (empty($task['end_time'])) {
                $task['end_time'] = '未结束';
            } else {
                $task['end_time'] = date('Y-m-d H:i:s', $task['end_time']);
            }
        }

        $data = [
            'code' => 0,
            'msg' => '',
            'count' => $taskList->total(),
            'data' => $taskListData
        ];

        return json($data);
    }

    // 任务添加页
    public function add()
    {
        // 找出当前用户所属的所有项目
        $userInfo = session('userInfo');
        $projectIds = UserProject::field('id,project_id')
            ->where('user_id', $userInfo['id'])
            ->column('project_id');
        $projects = \app\frontend\model\Project::field('id,name')->select($projectIds)->toArray();

        return view('', [
            'projects' => $projects
        ]);
    }

    // 富文本编辑器图片上传接口
    public function uploadImg()
    {
        $files = request()->file();
        $saveName = [];
        try {
            validate(['image' => ['fileSize:1024000', 'fileExt:jpg,png,gif,jpeg']])
                ->check($files);
            $ds = DIRECTORY_SEPARATOR;
            foreach($files as $file) {
                $saveName[] = $ds.'uploads'.$ds . Filesystem::disk('public')->putFile('image'.$ds.'temp', $file);
            }
        } catch (\think\exception\ValidateException $e) {
            return json([
                'errno' => 1,
                'data' => $e->getMessage()
            ]);
        }

        // 根据操作系统的不同对返回的saveName格式进行处理
        foreach ($saveName as &$v) {
            if ($ds == '/') {
                $v = str_replace('\\', $ds, $v);
            } else {
                $v = str_replace('/', $ds, $v);
            }
        }
        unset($v);

        return json([
            'errno' => 0,
            'data' => $saveName
        ]);
    }

    // 任务添加页面保存接口
    public function save()
    {
        $params['name'] = trim(input('post.name', '', 'strip_tags'));
        $params['project_id'] = trim(input('post.project', '', 'strip_tags'));
        $params['priority'] = trim(input('post.priority', '', 'strip_tags'));
        $params['type'] = trim(input('post.type', '', 'strip_tags'));
        $params['content'] = input('post.content', '');

        $validate = Validate::rule([
            'name|名称' => 'require|max:20',
            'priority|优先级' => 'require',
            'content|详情描述' => 'max:65535',
            'type|类型' => 'require'
        ]);
        if (!$validate->check($params)) {
            return json([
                'code' => 1,
                'msg' => $validate->getError()
            ]);
        }

        // 处理富文本编辑器传来的文本内容
        $newContent = $this->processContent($params['content']);

        // 启动事务
        Db::startTrans();
        try {
            $userInfo = session('userInfo');
            $taskModel = \app\frontend\model\Task::create([
                'name' => $params['name'],
                'project_id' => $params['project_id'],
                'status' => 1,
                'user_id' => $userInfo['id'],
                'priority' => $params['priority'],
                'type' => $params['type']
            ]);

            // 插入task_content表
            TaskContent::create([
                'task_id' => $taskModel->id,
                'content' => htmlspecialchars($newContent)
            ]);

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return json([
                'code' => 2,
                'msg' => $e->getMessage()
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '保存成功'
        ]);
    }

    // 任务查看编辑页
    public function edit()
    {
        // 任务信息
        $id = (int)input('get.id', '', 'strip_tags');
        $task = \app\frontend\model\Task::field('id,name,project_id,priority,type,symbol,addition_time')
            ->find($id);
        $task->taskContent();


        $project = \app\frontend\model\Project::field('id,name')->find($task['project_id'])->toArray();

        $taskData = [
            'id' => $id,
            'name' => $task['name'],
            'project_id' => $task['project_id'],
            'priority' => $task['priority'],
            'type' => $task['type'],
            'content' => $task['taskContent']['content'],
            'project' => $project['name'],
            'symbol' => $task['symbol'],
            'hour' => intval($task['addition_time'] / 3600),
            'minute' => ($task['addition_time'] % 3600) / 60
        ];

        return view('', [
            'task' => $taskData
        ]);
    }

    // 任务编辑页面保存接口
    public function update()
    {
        // 任务信息
        $params['id'] = (int)trim(input('post.id', '', 'strip_tags'));
        $params['name'] =  trim(input('post.name', '', 'strip_tags'));
        $params['priority'] = trim(input('post.priority', '', 'strip_tags'));
        $params['type'] = trim(input('post.type', '', 'strip_tags'));
        $params['content'] = input('post.content', '');
        $params['symbol'] =  trim(input('post.symbol', '', 'strip_tags'));
        $params['hour'] =  (int)trim(input('post.hour', '', 'strip_tags'));
        $params['minute'] =  (int)trim(input('post.minute', '', 'strip_tags'));

        // 格式验证
        $validate = Validate::rule([
            'id|id' => 'require|integer',
            'name|名称' => 'require|max:20',
            'priority|优先级' => 'require',
            'type|类型' => 'require'
        ]);
        if (!$validate->check($params)) {
            return json([
                'code' => 1,
                'msg' => $validate->getError()
            ]);
        }

        // 优先级参数设置
        switch ($params['priority']) {
            case '低':
                $params['priority'] = 1;
                break;
            case '中':
                $params['priority'] = 2;
                break;
            case '高':
                $params['priority'] = 3;
                break;
            default:
                return json([
                    'code' => 2,
                    'msg' => '优先级参数错误'
                ]);
        }

        // 类型参数设置
        switch ($params['type']) {
            case '需求任务':
                $params['type'] = 1;
                break;
            case '缺陷任务':
                $params['type'] = 2;
                break;
            default:
                return json([
                    'code' => 2,
                    'msg' => '类型参数错误'
                ]);
        }

        $taskModel = \app\frontend\model\Task::find($params['id']);

        // 富文本内容处理
        // 处理富文本编辑器传来的文本内容
        $newContent = $this->processContent($params['content']);
        // 找到原先content中存在但是富文本编辑器在本次编辑中删除的图片的url，然后删除该图片
        // 找到数据库中存储的content
        $oldContent = TaskContent::where('task_id', $params['id'])->find();
        $oldContent = htmlspecialchars_decode($oldContent['content']);
        // 正则表达式匹配查找图片路径
        $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
        preg_match_all($pattern, $oldContent, $oldMatches);
        $oldImgs = $oldMatches[1];
        preg_match_all($pattern, $newContent, $newMatches);
        $newImgs = $newMatches[1];
        // 删除图片
        for ($i=0; $i < count($oldImgs); $i++) {
            if (!in_array($oldImgs[$i], $newImgs)) {
                unlink('.' . $oldImgs[$i]);
            }
        }

        // 将数据存入数据库
        Db::startTrans();
        try {
            // 更新requirement表
            $taskModel->name = $params['name'];
            $taskModel->priority = $params['priority'];
            $taskModel->type = $params['type'];
            $taskModel->symbol = $params['symbol'];
            $taskModel->addition_time = $params['hour'] * 3600 + $params['minute'] * 60;
            $taskModel->save();
            // 更新task_content表
            $taskContent = TaskContent::where('task_id', $params['id'])->find();
            $taskContent->content =htmlspecialchars($newContent);
            $taskContent->save();

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            // 返回操作失败信息
            return json([
                'code' => 2,
                'msg' => '修改失败'
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '修改成功'
        ]);
    }

    // 开始任务
    public function start()
    {
        $id = (int)trim(input('post.id', '', 'strip_tags'));

        // 启动事务
        Db::startTrans();
        try {
            $task = \app\frontend\model\Task::find($id);
            $task->status = 2;
            $task->start_time = time();
            $task->save();

            TimeSlice::create([
                'task_id' => $id,
                'start_time' => $task->start_time
            ]);

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return json([
                'code' => 1,
                'msg' => $e->getMessage()
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '成功',
            'startTime' => date('Y-m-d H:i:s', $task->start_time)
        ]);
    }

    // 暂停任务
    public function pause()
    {
        $id = (int)trim(input('post.id', '', 'strip_tags'));

        // 启动事务
        Db::startTrans();
        try {
            $task = \app\frontend\model\Task::find($id);
            $task->status = 3;
            $task->save();

            $timeSlice = TimeSlice::where([
                'task_id' => $id,
                'end_time' => 0
            ])->find();
            $timeSlice->end_time = time();
            $timeSlice->save();

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return json([
                'code' => 1,
                'msg' => $e->getMessage()
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '成功'
        ]);
    }

    // 继续任务
    public function continue()
    {
        $id = (int)trim(input('post.id', '', 'strip_tags'));

        // 启动事务
        Db::startTrans();
        try {
            $task = \app\frontend\model\Task::find($id);
            $task->status = 2;
            $task->save();

            TimeSlice::create([
                'task_id' => $id,
                'start_time' => time()
            ]);

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return json([
                'code' => 1,
                'msg' => $e->getMessage()
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '成功'
        ]);
    }

    // 结束任务
    public function finish()
    {
        $id = (int)trim(input('post.id', '', 'strip_tags'));

        $task = \app\frontend\model\Task::find($id);
        if ($task->status == '进行中') { // 如果当前状态为进行中
            // 启动事务
            Db::startTrans();
            try {
                $task->status = 4;
                $task->end_time = time();
                $task->save();

                $timeSlice = TimeSlice::where([
                    'task_id' => $id,
                    'end_time' => 0
                ])->find();
                $timeSlice->end_time = $task->end_time;
                $timeSlice->save();

                // 提交事务
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                return json([
                    'code' => 1,
                    'msg' => $e->getMessage()
                ]);
            }
        } else { // 如果当前状态为暂停中
            $task->status = 4;
            $task->end_time = time();
            $task->save();
        }

        // 判断该任务的父任务的所有子任务是否都已经完成了，如果都完成了，把父任务的状态改成已完成
        // 如果该任务的父任务也完成了，那么还是按照同样的方法检查父任务的父任务
        $this->finishPTask($id);

        return json([
            'code' => 0,
            'msg' => '成功',
            'endTime' => date('Y-m-d H:i:s', $task->end_time)
        ]);
    }

    // 任务列表删除接口
    public function delete()
    {
        $id = (int)trim(input('post.id', '', 'strip_tags'));

        // 如果该任务有子任务，则需要先删除所有的子任务才能删除该任务
        $subTask = \app\frontend\model\Task::where('pid', $id)->find();
        if (!empty($subTask)) {
            return json([
                'code' => 2,
                'msg' => '需要先删除所有的子任务才能删除该任务'
            ]);
        }

        // 启动事务
        Db::startTrans();
        try {
            \app\frontend\model\Task::destroy($id);
            TimeSlice::destroy(function ($query) use ($id) {
                $query->where('task_id', $id);
            });

            // 删除富文本编辑器内容及内容中的图片
            $taskContentModel = TaskContent::where('task_id', $id)->find();
            $content = htmlspecialchars_decode($taskContentModel->content);
            $taskContentModel->delete();

            // 删除content中的图片
            $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
            preg_match_all($pattern, $content, $matches);
            $images = $matches[1];
            // 删除图片
            for ($i=0; $i < count($images); $i++) {
                unlink('.' . $images[$i]);
            }

            // 提交事务
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return json([
                'code' => 1,
                'msg' => $e->getMessage()
            ]);
        }

        return json([
            'code' => 0,
            'msg' => '删除成功'
        ]);
    }

    // 任务列表多选删除接口
    public function deleteMulti()
    {
        $ids = input('post.ids', '', 'strip_tags');

        // 如果所选任务有子任务，则需要先删除所有的子任务才能删除该任务
        $subTasks = \app\frontend\model\Task::where('pid', 'in', $ids)->select();
        if (!$subTasks->isEmpty()) {
            return json([
                'code' => 2,
                'msg' => '需要先删除所有的子任务才能删除该任务'
            ]);
        }

        // 挨个删除，如果失败则回滚
        foreach ($ids as $id) {
            Db::startTrans();
            try {
                \app\frontend\model\Task::destroy($id);
                TimeSlice::destroy(function ($query) use ($id) {
                    $query->where('task_id', '=', $id);
                });

                $taskContentModel = TaskContent::where('task_id', $id)->find();
                $content = htmlspecialchars_decode($taskContentModel->content);
                $taskContentModel->delete();

                // 删除content中的图片
                $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
                preg_match_all($pattern, $content, $matches);
                $images = $matches[1];
                // 删除图片
                for ($i=0; $i < count($images); $i++) {
                    unlink('.' . $images[$i]);
                }

                // 提交事务
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                // 返回操作失败信息
                return json([
                    'code' => 3,
                    'msg' => $e->getMessage()
                ]);
            }
        }

        return json([
            'code' => 0,
            'msg' => '删除成功'
        ]);
    }

    // 工时计算页面
    public function workHour()
    {
        // 找出当前用户所属的所有项目
        $userInfo = session('userInfo');
        $projectIds = UserProject::field('id,project_id')
            ->where('user_id', $userInfo['id'])
            ->column('project_id');
        $projects = \app\frontend\model\Project::field('id,name')->select($projectIds)->toArray();

        return view('', [
            'projects' => $projects
        ]);
    }

    // 计算总工时
    public function computeWorkHour()
    {
        $project = input('post.project', '', 'strip_tags');
        $startTime = input('post.startTime', '', 'strip_tags');
        $endTime = input('post.endTime', '', 'strip_tags');

        $startTime = strtotime($startTime);
        $endTime = strtotime($endTime);

        // 时间范围判断
        if ($startTime>time() || $endTime>time() || $startTime>$endTime) {
            return json([
                'code' => 1,
                'msg' => '时间选择错误'
            ]);
        }

        // 筛选任务
        $userInfo = session('userInfo');
        $taskList = \app\frontend\model\Task::field('id,name,start_time,end_time,status,pid')
            ->whereOr([
                [
                    ['user_id', '=', $userInfo['id']],
                    ['project_id', '=', $project],
                    ['status', '<>', '1'],
                    ['start_time', '<=', $endTime],
                    ['end_time', '>=', $startTime]
                ],
                [
                    ['user_id', '=', $userInfo['id']],
                    ['project_id', '=', $project],
                    ['status', '<>', '1'],
                    ['start_time', '<=', $endTime],
                    ['end_time', '=', 0]
                ]
            ])->select()->toArray();

        // 读取配置
        $userConfig = UserConfig::where('user_id', session('userInfo.id'))->find();
        if (empty($userConfig)) {
            // 默认配置
            $config = [
                'format' => 'his',
                'hour' => 7,
                'minute' => 0
            ];
        } else {
            $config = json_decode($userConfig->config, true);
        }

        // 对任务数据进行格式转换
        foreach ($taskList as $k=>&$v) {
            $v['start_time'] = date('Y-m-d H:i:s', $v['start_time']);
            if ($v['status'] == '进行中') {
                $v['end_time'] = '未结束';
            } else {
                $v['end_time'] = date('Y-m-d H:i:s', $v['end_time']);
            }

            // 计算每个任务的工时
            $workHour = $this->computeWorkHourByTaskIds([$v['id']], $startTime, $endTime);
            if ($workHour == 0) {
                // 如果该任务的工时为0，则在列表中删掉该任务，直接计算下一个任务的工时
                unset($taskList[$k]);
                continue;
            }
            if ($config['format'] == 'his') {
                // 如果配置的格式是时分秒格式
                // 把秒数转换成时分秒格式
                $hour = intval($workHour/3600);
                $minute = intval(($workHour%3600)/60);
                $second = ($workHour%3600)%60;
                $v['time'] = "{$hour}小时{$minute}分钟{$second}秒";
            } else {
                // 如果配置的格式是日格式
                $day = $workHour/((3600 * $config['hour']) + (60 * $config['minute']));
                $day = round($day, 1);
                $v['time'] = "{$day}天";
            }
        }
        unset($v);

        // 对得到的任务列表重新排序
        $taskListRes = [];
        foreach ($taskList as $v) {
            $taskListRes[] = $v;
        }

        // 计算总工时
        $taskIds = array_column($taskList, 'id');
        $workHour = $this->computeWorkHourByTaskIds($taskIds, $startTime, $endTime);
        if ($config['format'] == 'his') {
            // 如果配置的格式是时分秒格式
            // 把秒数转换成时分秒格式
            $hour = intval($workHour/3600);
            $minute = intval(($workHour%3600)/60);
            $second = ($workHour%3600)%60;
            $totalTime = "{$hour}小时{$minute}分钟{$second}秒";
        } else {
            // 如果配置的格式是日格式
            $day = $workHour/((3600 * $config['hour']) + (60 * $config['minute']));
            $day = round($day, 1);
            $totalTime = "{$day}天";
        }

        return json([
            'code' => 0,
            'data' => $taskListRes,
            'totalTime' => $totalTime,
            'msg' => '成功'
        ]);
    }

    // 单个任务工时计算
    public function itemWorkHour()
    {
        $id = (int)input('post.id', '', 'strip_tags');

        // 找到该任务的所有子任务的id
        $taskIds = $this->getAllSubTask($id);

        // 找到对应的时间片
        $timeSlice = TimeSlice::field('start_time,end_time')
            ->where('task_id', 'in', $taskIds)
            ->select()->toArray();

        $workHour = 0;
        foreach ($timeSlice as $v) {
            if ($v['end_time'] == 0) {
                $time = time() - $v['start_time'];
            } else {
                $time = $v['end_time'] - $v['start_time'];
            }
            $workHour += $time;
        }

        // 额外时间的计算
        $taskList = \app\frontend\model\Task::field('symbol,addition_time')
            ->select($taskIds);
        if (!$taskList->isEmpty()) {
            foreach ($taskList as $v) {
                if ($v['symbol'] == '+') {
                    $workHour += $v['addition_time'];
                } else {
                    $workHour -= $v['addition_time'];
                }
            }
        }

        // 把秒数转换成时分秒格式
        $hour = intval($workHour/3600);
        $minute = intval(($workHour%3600)/60);
        $second = ($workHour%3600)%60;

        return json([
            'code' => 0,
            'msg' => "{$hour}小时{$minute}分钟{$second}秒"
        ]);
    }

    // 子任务页面
    public function subTask()
    {

        return view();
    }

    // 时间片管理列表页
    public function timeSliceIndex()
    {
        $taskId = request()->param('id');

        return view('', [
            'taskId' => $taskId
        ]);
    }

    // 时间片管理列表
    public function timeSliceList()
    {
        $taskId = request()->param('id');
        $page = request()->param('page');
        $limit = request()->param('limit');

        $timeSliceList = TimeSlice::where('task_id', $taskId)
            ->order('id', 'desc')
            ->paginate([
                'list_rows' => $limit,
                'var_page' => 'page',
                'page' => $page
            ]);

        $timeSliceListData = $timeSliceList->toArray()['data'];
        foreach ($timeSliceListData as &$v) {
            $v['start_time'] = date('Y-m-d H:i:s', $v['start_time']);
            if ($v['end_time'] == 0) {
                $v['end_time'] = '未结束';
            } else {
                $v['end_time'] = date('Y-m-d H:i:s', $v['end_time']);
            }
        }
        unset($v);

        $data = [
            'code' => 0,
            'msg' => '',
            'count' => $timeSliceList->total(),
            'data' => $timeSliceListData
        ];
        return json($data);
    }

    // 时间片添加页面
    public function timeSliceAdd()
    {
        $taskId = request()->param('taskId');

        return view('', [
            'taskId' => $taskId
        ]);
    }

    // 时间片添加保存
    public function timeSliceSave()
    {
        $taskId = request()->param('taskId');
        $startTime = request()->param('startTime');
        $endTime = request()->param('endTime');

        TimeSlice::create([
            'task_id' => $taskId,
            'start_time' => strtotime($startTime),
            'end_time' => strtotime($endTime)
        ]);

        return json([
            'code' => 0,
            'msg' => '保存成功'
        ]);
    }

    // 时间片编辑页面
    public function timeSliceEdit()
    {
        $id = request()->param('id');

        $timeSlice = TimeSlice::find($id)->toArray();

        return view('', [
            'timeSlice' => $timeSlice
        ]);
    }

    // 时间片编辑页面保存
    public function timeSliceUpdate()
    {
        $id = request()->param('id');
        $startTime = request()->param('startTime');
        $endTime = input('post.endTime', '', 'strip_tags');
        if (empty($endTime)) {
            $endTime = 0;
        } else {
            $endTime = strtotime($endTime);
        }

        TimeSlice::update([
            'start_time' => strtotime($startTime),
            'end_time' => $endTime,
            'id' => $id
        ]);

        return json([
            'code' => 0,
            'msg' => '更新成功'
        ]);
    }

    // 时间片删除
    public function timeSliceDelete()
    {
        $id = request()->param('id');

        TimeSlice::destroy($id);

        return json([
            'code' => 0,
            'msg' => '删除成功'
        ]);
    }


    /**
     * 根据任务表的task_id计算工时
     * @param array $taskIds 任务id组成的数组
     * @param int $startTime 开始时间，unix时间戳格式
     * @param int $endTime 结束时间，unix时间戳格式
     * @return int 用秒数表示的时间
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function computeWorkHourByTaskIds($taskIds, $startTime, $endTime)
    {
        /* 工时计算 */
        $workHour = 0;

        /* 对于end_time=0的时间片计算 */
        // 找到end_time=0的时间片
        $timeSliceArray = TimeSlice::field('id,start_time,end_time')
            ->where([
                ['task_id', 'in', $taskIds],
                ['end_time', '=', 0]
            ])->select()->toArray();
        foreach ($timeSliceArray as &$v) {
            // 设置该时间片end_time为当前时间
            $v['end_time'] = time();

            // 分情况计算工时
            if ($v['start_time']>$startTime && $v['start_time']<$endTime && $v['end_time']>=$endTime) {
                // 情况1和情况2
                $time = $endTime - $v['start_time'];
            } elseif ($v['start_time']<=$startTime && $v['end_time']>=$endTime) {
                // 情况3和情况4和情况5
                $time = $endTime - $startTime;
            } else {
                $time = 0;
            }

            $workHour = $workHour + $time;
        }
        unset($v);

        /*对于end_time不为0的时间片的计算*/
        // 情况1
        $condition1 = TimeSlice::field('id,start_time,end_time')
            ->where([
                ['task_id', 'in', $taskIds],
                ['start_time', '>', $startTime],
                ['end_time', '<', $endTime],
                ['end_time', '<>', 0]
            ])->select()->toArray();
        foreach ($condition1 as $v) {
            $time = $v['end_time'] - $v['start_time'];
            $workHour = $workHour + $time;
        }
        // 情况2
        $condition2 = TimeSlice::field('start_time,end_time')
            ->where([
                ['task_id', 'in', $taskIds],
                ['start_time', '<', $startTime],
                ['end_time', '>', $endTime]
            ])->select()->toArray();
        foreach ($condition2 as $v) {
            $time = $endTime - $startTime;
            $workHour = $workHour + $time;
        }
        // 情况3
        $condition3 = TimeSlice::field('start_time,end_time')
            ->where([
                ['task_id', 'in', $taskIds],
                ['start_time', '>', $startTime],
                ['start_time', '<', $endTime],
                ['end_time', '>', $endTime]
            ])->select()->toArray();
        foreach ($condition3 as $v) {
            $time = $endTime - $v['start_time'];
            $workHour = $workHour + $time;
        }
        // 情况4
        $condition4 = TimeSlice::field('start_time,end_time')
            ->where([
                ['task_id', 'in', $taskIds],
                ['end_time', '>', $startTime],
                ['end_time', '<', $endTime],
                ['start_time', '<', $startTime]
            ])->select()->toArray();
        foreach ($condition4 as $v) {
            $time = $v['end_time'] - $startTime;
            $workHour = $workHour + $time;
        }
        // 情况7
        $condition7 = TimeSlice::field('start_time,end_time')
            ->where([
                ['task_id', 'in', $taskIds],
                ['start_time', '=', $startTime],
                ['end_time', '=', $endTime]
            ])->select()->toArray();
        foreach ($condition7 as $v) {
            $time = $v['end_time'] - $v['start_time'];
            $workHour = $workHour + $time;
        }

        // 额外时间的计算
        $taskList = \app\frontend\model\Task::field('symbol,addition_time')
            ->select($taskIds);
        if (!$taskList->isEmpty()) {
            foreach ($taskList as $v) {
                if ($v['symbol'] == '+') {
                    $workHour += $v['addition_time'];
                } else {
                    $workHour -= $v['addition_time'];
                }
            }
        }

        return $workHour;
    }

    /**
     * 获取$id的所有子任务id
     * @param integer $id 任务id
     * @return array 所有任务的id的数组，数组中包含$id
     */
    private function getAllSubTask($id)
    {
        $exist = \app\frontend\model\Task::where('pid', $id)->find();
        if (empty($exist)) {
            return [$id];
        } else {
            $subTaskIds = \app\frontend\model\Task::where('pid', $id)->column('id');
            $ids = [];
            foreach ($subTaskIds as $subTaskId) {
                $ids = array_merge($ids, $this->getAllSubTask($subTaskId));
            }
            array_push($ids, $id);
            return $ids;
        }
    }

    /**
     * 递归结束父级任务
     * @param int $id
     */
    private function finishPTask(int $id)
    {
        $task = \app\frontend\model\Task::find($id);
        if ($task->pid == 0) {
            if ($task->plan_id != 0) { // 如果该任务关联了计划
                // 将关联的计划的状态置为3已完成并设置完成时间
                \app\frontend\model\Plan::update(['status' => 3, 'finish_time' => time()], ['id' => $task->plan_id]);
            }
            return;
        } else {
            $siblingTasks = \app\frontend\model\Task::where('pid', $task->pid)->select();
            $flag = true;
            foreach ($siblingTasks as $siblingTask) {
                if ($siblingTask['status'] != '已完成') {
                    $flag = false;
                }
            }
            if ($flag) {
                \app\frontend\model\Task::update(['status' => 4, 'end_time' => time()], ['id' => $task->pid]);
                $this->finishPTask($task->pid);
            }
        }
    }

    /**
     * 富文本编辑器文本内容处理
     * @param string $content 富文本编辑器文本内容
     * @return bool|mixed|null 处理的结果
     */
    private function processContent($content)
    {
        // 转移图片
        if (!empty($content)) {
            // 已经存在的图片
            $imgArray = [];
            // 完成处理的content
            $newContent = null;

            $ds = DIRECTORY_SEPARATOR;

            // 正则表达式匹配查找图片路径
            $pattern = '/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.jpeg|\.png]))[\'|\"].*?[\/]?>/i';
            preg_match_all($pattern, $content, $matches);
            $count = count($matches[1]);
            for ($i=0; $i < $count; $i++) {
                $editorImg = $matches[1][$i];
                // 根据操作系统的不同对返回的saveName格式进行处理
                if ($ds == '/') {
                    $editorImg = str_replace('\\', $ds, $editorImg);
                } else {
                    $editorImg = str_replace('/', $ds, $editorImg);
                }
                // 判断是否是新上传的图片
                $position = stripos($editorImg, $ds."temp".$ds);
                if ($position > 0) {    // 新上传的图片走这里
                    // 将图片从临时temp文件夹中迁移到article文件夹中
                    // 传过来的临时文件路径为：/uploads/image/temp/20201030/d885cc3b24b184a7c631408b5e0f670e.jpg
                    // 要迁移的文件路径：/uploads/image/article/20201030/d885cc3b24b184a7c631408b5e0f670e.jpg
                    // 新建日期文件夹
                    $tempArray = explode($ds, $editorImg);
                    $imageFloder = '.'.$ds.'uploads'.$ds.'image'.$ds.'task'.$ds . $tempArray[4];
                    if (!is_dir($imageFloder)) {
                        mkdir($imageFloder, 0777, true);
                    }
                    $tempImg = '.' . $editorImg;
                    $newImg = str_replace($ds.'temp'.$ds, $ds.'task'.$ds, $tempImg);
                    // 转移图片
                    rename($tempImg, $newImg);
                } else {
                    // 已经存在的图片走这里
                    $imgArray[] = $editorImg;
                }
            }

            // 重新整理content中的图片路径
            $newContent = str_replace($ds.'temp'.$ds, $ds.'task'.$ds, $content);
            return $newContent;
        }

        return false;
    }
}
